home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / libray / libtext / gradient.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  3.2 KB  |  134 lines

  1. /*
  2.  * gradient.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb, 1992, Lawrence Coffin
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  * 
  16.  */
  17.  
  18. #include "libcommon/common.h"
  19. #include "libcommon/color.h"
  20. #include "texture.h"
  21. #include "gradient.h"
  22.  
  23. #define sign(x)  ((x) < 0 ? (-1) : (1))
  24.  
  25. Gradient *
  26. GradientCreate(surf1, surf2, Shape, start, stop, GradType, Rand)
  27. Surface *surf1, *surf2;
  28. Float start, stop;
  29. int Shape, GradType, Rand;
  30. {
  31.     Gradient *grad;
  32.  
  33.     if (start > stop){
  34.         RLerror(RL_WARN,"Bad Gradient range\n");
  35.         return (Gradient *)NULL;
  36.     }
  37.  
  38.     grad = (Gradient *)Malloc(sizeof(Gradient));
  39.     grad->surf1 = surf1;
  40.     if (surf1 == surf2){
  41.         grad->surf2 = (Surface *)NULL;
  42.     }
  43.     else {
  44.         grad->surf2 = surf2;
  45.     }
  46.     grad->start = start;
  47.     grad->stop = stop;
  48.     grad->shape = Shape;
  49.     grad->type = GradType;
  50.     grad->rand = Rand;
  51.  
  52.     return grad;
  53.  
  54.  
  55. }
  56.  
  57. /* Basically this texture works by calculating the distance of the point
  58.  * "pos" according to the texture's shape.  Then the distance is normalized
  59.  * between the starting and stoping distances for the texture and changed
  60.  * according to the gradient type.  Finally, if the resulting distance
  61.  * is between 0 and 1, the original surface is replaced with the texture's
  62.  * first surface the blended with the second surface according to the
  63.  * distance -- final surface = surf1*(1-dist) + surf2*dist
  64.  */
  65.  
  66. void
  67. GradientApply(grad,prim,ray,pos,norm,gnorm,surf)
  68. Gradient *grad;
  69. Geom *prim;
  70. Ray *ray;
  71. Vector *pos, *norm, *gnorm;
  72. Surface *surf;
  73. {
  74.     Float len, side;
  75.  
  76.     /* calculate the distance of the point according to the shape */
  77.     if (grad->shape == PLANAR){
  78.         len = pos->z;
  79.         side = sqrt(pos->x*pos->x + pos->y*pos->y);
  80.     }
  81.     else if (grad->shape == RADIAL){
  82.         len = sqrt(pos->x*pos->x + pos->y*pos->y);
  83.         if (pos->x != 0.0){
  84.             side = atan(pos->y/pos->x);
  85.         }
  86.         else side = PI/2.0;
  87.     }
  88.     else if (grad->shape == SPHERICAL){
  89.         len = sqrt(pos->x*pos->x + pos->y*pos->y + pos->z*pos->z);
  90.  
  91.         side = sqrt(pos->x*pos->x + pos->y*pos->y);
  92.         if (pos->z != 0.0){
  93.             side = atan(side/pos->z);
  94.         }
  95.         else side = PI/2.0;
  96.     }
  97.  
  98.     /* normalize it between the start and stop distances */
  99.     len = (len - grad->start)/(grad->stop - grad->start);
  100.  
  101.     /* add random noise based on the point in 3-space */
  102.     if (grad->rand) {
  103.         len += Noise3(pos);
  104.     }
  105.  
  106.     /* modify according to Type -- linear remains the same */
  107.     if (grad->type == LOG){
  108.         len = sqrt(len);
  109.     }
  110.     else if (grad->type == REVLOG){
  111.         len = len*len*sign(len);
  112.     }
  113.  
  114.     /* check to see if the point is between 0 and 1 */
  115.     if (len < 0 - EPSILON || len > 1 + EPSILON) {
  116.         /* point is outside of texture range */
  117.         return;
  118.     }
  119.  
  120.  
  121.  
  122.     /* set surface to first surface */
  123.     *surf = *grad->surf1;
  124.  
  125.     /* check to see if there is a second surface */
  126.     if (grad->surf2 == (Surface *)NULL){
  127.         return;
  128.     }
  129.  
  130.     /* blend the two surfaces based on the length of len */
  131.     SurfaceBlend(surf,grad->surf2,1-len,len);
  132. }
  133.  
  134.